{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[32m2024-07-06 12:45:50.026\u001b[0m | \u001b[1mINFO    \u001b[0m | \u001b[36mbyzerllm.utils.connect_ray\u001b[0m:\u001b[36mconnect_cluster\u001b[0m:\u001b[36m37\u001b[0m - \u001b[1mJDK 21 will be used (/Users/allwefantasy/.auto-coder/jdk-21.0.2.jdk/Contents/Home)...\u001b[0m\n",
      "2024-07-06 12:45:50,198\tINFO worker.py:1564 -- Connecting to existing Ray cluster at address: 127.0.0.1:6379...\n",
      "2024-07-06 12:45:50,211\tINFO worker.py:1740 -- Connected to Ray cluster. View the dashboard at \u001b[1m\u001b[32m127.0.0.1:8265 \u001b[39m\u001b[22m\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "21\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Building prefix dict from the default dictionary ...\n",
      "Loading model from cache /var/folders/dm/0xljd5nn10b7bwwmwv8w5v100000gn/T/jieba.cache\n",
      "Loading model cost 0.668 seconds.\n",
      "Prefix dict has been built successfully.\n",
      "2024-07-06 12:45:51,845\tWARNING __init__.py:158 -- DeprecationWarning: `ray.worker.global_worker` is a private attribute and access will be removed in a future Ray version.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'name': 'Hello', 'created_time': 1612137600, 'raw_content': 'Hello, world!', '_id': '1', '_score': 0.032539684}, {'name': 'ByzerAI', 'created_time': 16121376003, 'raw_content': 'ByzerAI, world!', '_id': '4', '_score': 0.016666668}, {'name': 'Byzer', 'created_time': 1612137601, 'raw_content': 'Byzer, world!', '_id': '2', '_score': 0.016393442}, {'name': 'AI', 'created_time': 16121376002, 'raw_content': 'AI, world!', '_id': '3', '_score': 0.016129032}]\n",
      "[{'name': 'AI', 'created_time': 16121376002, 'raw_content': 'AI, world!', '_id': '3', '_score': 0.033333335}]\n",
      "[{'name': 'AI', 'created_time': 16121376002, 'raw_content': 'AI, world!', '_id': '3'}]\n",
      "{'and': [{'field': 'name', 'value': 'AI'}]}\n",
      "====\n",
      "[{'name': 'AI', 'created_time': 16121376002, 'raw_content': 'AI, world!', '_id': '3'}]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[33m(raylet)\u001b[0m java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Long (java.lang.String and java.lang.Long are in module java.base of loader 'bootstrap')\n",
      "\u001b[33m(raylet)\u001b[0m \tat tech.mlsql.retrieval.schema.SchemaUtils.toLuceneQuery(SchemaUtils.java:188)\n",
      "\u001b[33m(raylet)\u001b[0m \tat io.ray.runtime.RayNativeRuntime.nativeRunTaskExecutor(Native Method)\n",
      "\u001b[33m(raylet)\u001b[0m WARNING: Using incubator modules: jdk.incubator.vector\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[33m(raylet)\u001b[0m The autoscaler failed with the following error:\n",
      "Terminated with signal 15\n",
      "  File \"/opt/miniconda3/envs/byzerllm/lib/python3.10/site-packages/ray/autoscaler/_private/monitor.py\", line 709, in <module>\n",
      "    monitor.run()\n",
      "  File \"/opt/miniconda3/envs/byzerllm/lib/python3.10/site-packages/ray/autoscaler/_private/monitor.py\", line 584, in run\n",
      "    self._run()\n",
      "  File \"/opt/miniconda3/envs/byzerllm/lib/python3.10/site-packages/ray/autoscaler/_private/monitor.py\", line 438, in _run\n",
      "    time.sleep(AUTOSCALER_UPDATE_INTERVAL_S)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from byzerllm.apps.byzer_storage.simple_api import ByzerStorage, DataType, FieldOption,SortOption\n",
    "\n",
    "# 初始化 EasyStorage\n",
    "storage = ByzerStorage(\"byzerai_store\", \"my_database1\", \"my_table4s\")\n",
    "_ = (\n",
    "    storage.schema_builder()\n",
    "    ## 主键，字符串\n",
    "    .add_field(\"_id\", DataType.STRING)\n",
    "    ## 可以作为where条件过滤的字段\n",
    "    .add_field(\"name\", DataType.STRING)\n",
    "    ## 可以作为搜索字段\n",
    "    .add_field(\"content\", DataType.STRING, [FieldOption.ANALYZE])\n",
    "    ## 不需要索引的字段，会原模原样存储\n",
    "    .add_field(\"raw_content\", DataType.STRING, [FieldOption.NO_INDEX])    \n",
    "    ## 数组字段\n",
    "    .add_array_field(\"summary\", DataType.FLOAT)    \n",
    "    ## 需要排序的字段\n",
    "    .add_field(\"created_time\", DataType.LONG, [FieldOption.SORT])    \n",
    "    .execute()\n",
    ")\n",
    "\n",
    "## st(\n",
    "# field(_id,long),\n",
    "# field(name,string),\n",
    "# field(content,string,analyze),\n",
    "# field(raw_content,string,no_index),\n",
    "# field(summary,array(float)),\n",
    "# field(created_time,long,sort)\n",
    "# )\n",
    "\n",
    "# 准备数据\n",
    "data = [\n",
    "    {\"_id\": \"1\", \"name\": \"Hello\", \"content\": \"Hello, world!\", \"raw_content\": \"Hello, world!\", \"summary\": \"hello world\", \"created_time\": 1612137600},\n",
    "    {\"_id\": \"2\", \"name\": \"Byzer\", \"content\": \"Byzer, world!\", \"raw_content\": \"Byzer, world!\", \"summary\": \"byzer\", \"created_time\": 1612137601},\n",
    "    {\"_id\": \"3\", \"name\": \"AI\", \"content\": \"AI, world!\", \"raw_content\": \"AI, world!\", \"summary\": \"AI\", \"created_time\": 16121376002},\n",
    "    {\"_id\": \"4\", \"name\": \"ByzerAI\", \"content\": \"ByzerAI, world!\", \"raw_content\": \"ByzerAI, world!\", \"summary\": \"ByzerAi\", \"created_time\": 16121376003},\n",
    "]\n",
    "\n",
    "# 写入Storage\n",
    "storage.write_builder().add_items(data,vector_fields=[\"summary\"],search_fields=[\"content\"]).execute()\n",
    "\n",
    "# commit 写入\n",
    "storage.commit()\n",
    "\n",
    "# 搜索\n",
    "query = storage.query_builder()\n",
    "query.set_vector_query(\"ByzerAi\",fields=[\"summary\"])\n",
    "results = query.set_search_query(\"Hello\",fields=[\"content\"]).execute()\n",
    "print(results)\n",
    "\n",
    "## 过滤之后再做搜索\n",
    "query = storage.query_builder()\n",
    "query.and_filter().add_condition(\"name\",\"AI\").build()\n",
    "query.set_vector_query(\"ByzerAi\",fields=\"summary\")\n",
    "results = query.set_search_query(\"Hello\",fields=[\"content\"]).execute()\n",
    "print(results)\n",
    "\n",
    "## 过滤再做排序\n",
    "query = storage.query_builder()\n",
    "query.and_filter().add_condition(\"name\",\"AI\").build().sort(\"created_time\",SortOption.DESC)\n",
    "results = query.execute()\n",
    "print(results)\n",
    "\n",
    "## 根据ID做删除\n",
    "storage.delete_by_ids([\"3\"])\n",
    "\n",
    "query = storage.query_builder()\n",
    "query.and_filter().add_condition(\"name\",\"AI\").build()\n",
    "results = query.execute()\n",
    "print(\"====\")\n",
    "print(results)\n",
    "\n",
    "## 删除表\n",
    "storage.drop_table()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'and': [{'field': 'name', 'value': 'AI'}]}\n",
      "====\n",
      "[]\n"
     ]
    },
    {
     "ename": "",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31mThe Kernel crashed while executing code in the current cell or a previous cell. \n",
      "\u001b[1;31mPlease review the code in the cell(s) to identify a possible cause of the failure. \n",
      "\u001b[1;31mClick <a href='https://aka.ms/vscodeJupyterKernelCrash'>here</a> for more info. \n",
      "\u001b[1;31mView Jupyter <a href='command:jupyter.viewOutput'>log</a> for further details."
     ]
    }
   ],
   "source": [
    "from byzerllm.apps.byzer_storage.simple_api import ByzerStorage, DataType, FieldOption,SortOption\n",
    "storage = ByzerStorage(\"byzerai_store\", \"my_database1\", \"my_table4s\")\n",
    "## 根据过滤条件删除数据\n",
    "storage.query_builder().and_filter().add_condition(\"name\",\"AI\").build().delete()\n",
    "# storage.delete_by_ids([\"3\"])\n",
    "\n",
    "query = storage.query_builder()\n",
    "query.and_filter().add_condition(\"name\",\"AI\").build()\n",
    "results = query.execute()\n",
    "print(\"====\")\n",
    "print(results)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[32m2024-07-29 14:00:23.540\u001b[0m | \u001b[1mINFO    \u001b[0m | \u001b[36mbyzerllm.utils.connect_ray\u001b[0m:\u001b[36mconnect_cluster\u001b[0m:\u001b[36m48\u001b[0m - \u001b[1mJDK 21 will be used (/Users/allwefantasy/.auto-coder/jdk-21.0.2.jdk/Contents/Home)...\u001b[0m\n",
      "2024-07-29 14:00:23,688\tINFO worker.py:1564 -- Connecting to existing Ray cluster at address: 127.0.0.1:6379...\n",
      "2024-07-29 14:00:23,703\tINFO worker.py:1740 -- Connected to Ray cluster. View the dashboard at \u001b[1m\u001b[32m127.0.0.1:8265 \u001b[39m\u001b[22m\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "21\n"
     ]
    }
   ],
   "source": [
    "from byzerllm.apps.byzer_storage.simple_api import ByzerStorage, DataType, FieldOption,SortOption\n",
    "\n",
    "# 初始化 EasyStorage\n",
    "storage = ByzerStorage(\"byzerai_store\", \"memory\", \"memory\")\n",
    "_ = (\n",
    "    storage.schema_builder()\n",
    "    ## 主键，字符串\n",
    "    .add_field(\"_id\", DataType.STRING)\n",
    "    ## 可以作为where条件过滤的字段\n",
    "    .add_field(\"name\", DataType.STRING)\n",
    "    ## 可以作为搜索字段\n",
    "    .add_field(\"content\", DataType.STRING, [FieldOption.ANALYZE])\n",
    "    ## 不需要索引的字段，会原模原样存储\n",
    "    .add_field(\"raw_content\", DataType.STRING, [FieldOption.NO_INDEX])    \n",
    "    ## 数组字段\n",
    "    .add_array_field(\"summary\", DataType.FLOAT)    \n",
    "    ## 需要排序的字段\n",
    "    .add_field(\"created_time\", DataType.LONG, [FieldOption.SORT])    \n",
    "    .execute()\n",
    ")\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1722233112"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "int(time.time())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "import uuid\n",
    "def memorize(name:str,s:str):\n",
    "    data = [\n",
    "        {\"_id\": str(uuid.uuid4()), \"name\": name, \"content\": s, \"raw_content\": s, \"summary\": s, \"created_time\": int(time.time())},    \n",
    "    ]\n",
    "    storage.write_builder().add_items(data,vector_fields=[\"summary\"],search_fields=[\"content\"]).execute()\n",
    "\n",
    "def recall(name:str,query:str):\n",
    "    searcher = storage.query_builder()\n",
    "    searcher.and_filter().add_condition(\"name\",name).build()\n",
    "    searcher.set_vector_query(query,fields=\"summary\")\n",
    "    results = searcher.set_search_query(query,fields=[\"content\"]).execute() \n",
    "    return results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "storage.delete_by_ids([\"1\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "memorize(\"william\",\"William的生日是2月1号\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'name': 'william',\n",
       "  'created_time': 1722233443,\n",
       "  'raw_content': 'William的生日是2月1号',\n",
       "  '_id': 'f7fcb7b6-e5d2-493d-99c4-b1a48c23e91a',\n",
       "  '_score': 0.033333335}]"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "recall(\"william\",\"William生日是几号\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[32m2024-07-29 14:14:24.362\u001b[0m | \u001b[1mINFO    \u001b[0m | \u001b[36mbyzerllm.utils.connect_ray\u001b[0m:\u001b[36mconnect_cluster\u001b[0m:\u001b[36m48\u001b[0m - \u001b[1mJDK 21 will be used (/Users/allwefantasy/.auto-coder/jdk-21.0.2.jdk/Contents/Home)...\u001b[0m\n",
      "2024-07-29 14:14:24,469\tINFO worker.py:1564 -- Connecting to existing Ray cluster at address: 127.0.0.1:6379...\n",
      "2024-07-29 14:14:24,471\tINFO worker.py:1582 -- Calling ray.init() again after it has already been called.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'根据提供的信息，William的生日是2月1号。'"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import byzerllm\n",
    "import json\n",
    "\n",
    "llm = byzerllm.ByzerLLM.from_default_model(\"deepseek_chat\")\n",
    "\n",
    "@byzerllm.prompt(llm=llm)\n",
    "def ask_about_william(query:str)->str:\n",
    "    '''\n",
    "    根据下面的信息回答用户的问题。\n",
    "\n",
    "    {{ context }}\n",
    "\n",
    "    用户的问题：\n",
    "\n",
    "    {{ query }}\n",
    "    '''\n",
    "    return {\n",
    "        \"context\": json.dumps(recall(\"william\",query),ensure_ascii=False)\n",
    "    }\n",
    "\n",
    "ask_about_william(\"William的生日是几号\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "byzerllm",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
